home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Tools / Languages / Python 1.1 / Modules / posixmodule.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-29  |  26.9 KB  |  1,456 lines  |  [TEXT/KAHL]

  1. /***********************************************************
  2. Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum,
  3. Amsterdam, The Netherlands.
  4.  
  5.                         All Rights Reserved
  6.  
  7. Permission to use, copy, modify, and distribute this software and its 
  8. documentation for any purpose and without fee is hereby granted, 
  9. provided that the above copyright notice appear in all copies and that
  10. both that copyright notice and this permission notice appear in 
  11. supporting documentation, and that the names of Stichting Mathematisch
  12. Centrum or CWI not be used in advertising or publicity pertaining to
  13. distribution of the software without specific, written prior permission.
  14.  
  15. STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
  16. THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  17. FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
  18. FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19. WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  20. ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  21. OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  
  23. ******************************************************************/
  24.  
  25. /* POSIX module implementation */
  26.  
  27. #include "allobjects.h"
  28. #include "modsupport.h"
  29. #include "ceval.h"
  30.  
  31. #include <string.h>
  32. #include <errno.h>
  33. #include <sys/types.h>
  34. #include <sys/stat.h>
  35.  
  36. #include "mytime.h"        /* For clock_t on some systems */
  37.  
  38. #ifdef HAVE_FCNTL_H
  39. #include <fcntl.h>
  40. #endif /* HAVE_FCNTL_H */
  41.  
  42. #ifndef NT
  43. #ifdef HAVE_UNISTD_H
  44. #include <unistd.h>
  45. #else /* !HAVE_UNISTD_H */
  46. extern int mkdir PROTO((const char *, mode_t));
  47. extern int chdir PROTO((const char *));
  48. extern int rmdir PROTO((const char *));
  49. extern int chmod PROTO((const char *, mode_t));
  50. extern int chown PROTO((const char *, uid_t, gid_t));
  51. extern char *getcwd PROTO((char *, int));
  52. extern char *strerror PROTO((int));
  53. extern int link PROTO((const char *, const char *));
  54. extern int rename PROTO((const char *, const char *));
  55. extern int stat PROTO((const char *, struct stat *));
  56. extern int unlink PROTO((const char *));
  57. extern int pclose PROTO((FILE *));
  58. #ifdef HAVE_SYMLINK
  59. extern int symlink PROTO((const char *, const char *));
  60. #endif /_ HAVE_SYMLINK */
  61. #ifdef HAVE_LSTAT
  62. extern int lstat PROTO((const char *, struct stat *));
  63. #endif /* HAVE_LSTAT */
  64. #endif /* !HAVE_UNISTD_H */
  65. #endif /* !NT */
  66.  
  67. #ifndef NT
  68. /* XXX These are for SunOS4.1.3 but shouldn't hurt elsewhere */
  69. extern int rename();
  70. extern int pclose();
  71. extern int lstat();
  72. extern int symlink();
  73. #endif /* !NT */
  74.  
  75. #ifdef HAVE_UTIME_H
  76. #include <utime.h>
  77. #endif /* HAVE_UTIME_H */
  78.  
  79. #ifdef HAVE_SYS_UTIME_H
  80. #include <sys/utime.h>
  81. #define HAVE_UTIME_H /* pretend we do for the rest of this file */
  82. #endif /* HAVE_SYS_UTIME_H */
  83.  
  84. #ifdef HAVE_SYS_TIMES_H
  85. #include <sys/times.h>
  86. #endif /* HAVE_SYS_TIMES_H */
  87.  
  88. #ifdef HAVE_SYS_PARAM_H
  89. #include <sys/param.h>
  90. #endif /* HAVE_SYS_PARAM_H */
  91.  
  92. #ifdef HAVE_SYS_UTSNAME_H
  93. #include <sys/utsname.h>
  94. #endif /* HAVE_SYS_UTSNAME_H */
  95.  
  96. #ifndef MAXPATHLEN
  97. #define MAXPATHLEN 1024
  98. #endif /* MAXPATHLEN */
  99.  
  100. /* unistd.h defines _POSIX_VERSION on POSIX.1 systems.  */
  101. #if defined(DIRENT) || defined(_POSIX_VERSION)
  102. #include <dirent.h>
  103. #define NLENGTH(dirent) (strlen((dirent)->d_name))
  104. #else /* not (DIRENT or _POSIX_VERSION) */
  105. #define dirent direct
  106. #define NLENGTH(dirent) ((dirent)->d_namlen)
  107. #ifdef SYSNDIR
  108. #include <sys/ndir.h>
  109. #endif /* SYSNDIR */
  110. #ifdef SYSDIR
  111. #include <sys/dir.h>
  112. #endif /* SYSDIR */
  113. #ifdef NDIR
  114. #include <ndir.h>
  115. #endif /* NDIR */
  116. #endif /* not (DIRENT or _POSIX_VERSION) */
  117.  
  118. #ifdef NT
  119. #include <direct.h>
  120. #include <io.h>
  121. #include <process.h>
  122. #include <windows.h>
  123. #define popen   _popen
  124. #define pclose    _pclose
  125. #endif /* NT */
  126.  
  127. #ifdef OS2
  128. #include <io.h>
  129. #endif /* OS2 */
  130.  
  131. /* Return a dictionary corresponding to the POSIX environment table */
  132.  
  133. #ifndef NT
  134. extern char **environ;
  135. #endif /* !NT */
  136.  
  137. static object *
  138. convertenviron()
  139. {
  140.     object *d;
  141.     char **e;
  142.     d = newdictobject();
  143.     if (d == NULL)
  144.         return NULL;
  145.     if (environ == NULL)
  146.         return d;
  147.     /* XXX This part ignores errors */
  148.     for (e = environ; *e != NULL; e++) {
  149.         object *v;
  150.         char *p = strchr(*e, '=');
  151.         if (p == NULL)
  152.             continue;
  153.         v = newstringobject(p+1);
  154.         if (v == NULL)
  155.             continue;
  156.         *p = '\0';
  157.         (void) dictinsert(d, *e, v);
  158.         *p = '=';
  159.         DECREF(v);
  160.     }
  161.     return d;
  162. }
  163.  
  164.  
  165. static object *PosixError; /* Exception posix.error */
  166.  
  167. /* Set a POSIX-specific error from errno, and return NULL */
  168.  
  169. static object * posix_error() {     return err_errno(PosixError);
  170. }
  171.  
  172.  
  173. /* POSIX generic methods */
  174.  
  175. static object *
  176. posix_1str(args, func)
  177.     object *args;
  178.     int (*func) FPROTO((const char *));
  179. {
  180.     char *path1;
  181.     int res;
  182.     if (!getargs(args, "s", &path1))
  183.         return NULL;
  184.     BGN_SAVE
  185.     res = (*func)(path1);
  186.     END_SAVE
  187.     if (res < 0)
  188.         return posix_error();
  189.     INCREF(None);
  190.     return None;
  191. }
  192.  
  193. static object *
  194. posix_2str(args, func)
  195.     object *args;
  196.     int (*func) FPROTO((const char *, const char *));
  197. {
  198.     char *path1, *path2;
  199.     int res;
  200.     if (!getargs(args, "(ss)", &path1, &path2))
  201.         return NULL;
  202.     BGN_SAVE
  203.     res = (*func)(path1, path2);
  204.     END_SAVE
  205.     if (res < 0)
  206.         return posix_error();
  207.     INCREF(None);
  208.     return None;
  209. }
  210.  
  211. static object *
  212. posix_strint(args, func)
  213.     object *args;
  214.     int (*func) FPROTO((const char *, int));
  215. {
  216.     char *path;
  217.     int i;
  218.     int res;
  219.     if (!getargs(args, "(si)", &path, &i))
  220.         return NULL;
  221.     BGN_SAVE
  222.     res = (*func)(path, i);
  223.     END_SAVE
  224.     if (res < 0)
  225.         return posix_error();
  226.     INCREF(None);
  227.     return None;
  228. }
  229.  
  230. static object *
  231. posix_strintint(args, func)
  232.     object *args;
  233.     int (*func) FPROTO((const char *, int, int));
  234. {
  235.     char *path;
  236.     int i,i2;
  237.     int res;
  238.     if (!getargs(args, "(sii)", &path, &i, &i2))
  239.         return NULL;
  240.     BGN_SAVE
  241.     res = (*func)(path, i, i2);
  242.     END_SAVE
  243.     if (res < 0)
  244.         return posix_error();
  245.     INCREF(None);
  246.     return None;
  247. }
  248.  
  249. static object *
  250. posix_do_stat(self, args, statfunc)
  251.     object *self;
  252.     object *args;
  253.     int (*statfunc) FPROTO((const char *, struct stat *));
  254. {
  255.     struct stat st;
  256.     char *path;
  257.     int res;
  258.     if (!getargs(args, "s", &path))
  259.         return NULL;
  260.     BGN_SAVE
  261.     res = (*statfunc)(path, &st);
  262.     END_SAVE
  263.     if (res != 0)
  264.         return posix_error();
  265.     return mkvalue("(llllllllll)",
  266.             (long)st.st_mode,
  267.             (long)st.st_ino,
  268.             (long)st.st_dev,
  269.             (long)st.st_nlink,
  270.             (long)st.st_uid,
  271.             (long)st.st_gid,
  272.             (long)st.st_size,
  273.             (long)st.st_atime,
  274.             (long)st.st_mtime,
  275.             (long)st.st_ctime);
  276. }
  277.  
  278.  
  279. /* POSIX methods */
  280.  
  281. static object *
  282. posix_chdir(self, args)
  283.     object *self;
  284.     object *args;
  285. {
  286.     return posix_1str(args, chdir);
  287. }
  288.  
  289. static object *
  290. posix_chmod(self, args)
  291.     object *self;
  292.     object *args;
  293. {
  294.     return posix_strint(args, chmod);
  295. }
  296.  
  297. #ifdef HAVE_CHOWN
  298. static object *
  299. posix_chown(self, args)
  300.     object *self;
  301.     object *args;
  302. {
  303.     return posix_strintint(args, chown);
  304. }
  305. #endif /* HAVE_CHOWN */
  306.  
  307. static object *
  308. posix_getcwd(self, args)
  309.     object *self;
  310.     object *args;
  311. {
  312.     char buf[1026];
  313.     char *res;
  314.     if (!getnoarg(args))
  315.         return NULL;
  316.     BGN_SAVE
  317.     res = getcwd(buf, sizeof buf);
  318.     END_SAVE
  319.     if (res == NULL)
  320.         return posix_error();
  321.     return newstringobject(buf);
  322. }
  323.  
  324. #ifdef HAVE_LINK
  325. static object *
  326. posix_link(self, args)
  327.     object *self;
  328.     object *args;
  329. {
  330.     return posix_2str(args, link);
  331. }
  332. #endif /* HAVE_LINK */
  333.  
  334. static object *
  335. posix_listdir(self, args)
  336.     object *self;
  337.     object *args;
  338. {
  339. #ifdef NT
  340.  
  341.     char *name;
  342.     int len;
  343.     object *d, *v;
  344.     HANDLE hFindFile;
  345.     WIN32_FIND_DATA FileData;
  346.     char namebuf[MAX_PATH+5];
  347.  
  348.     if (!getargs(args, "s#", &name, &len))
  349.         return NULL;
  350.     if (len >= MAX_PATH) {
  351.         err_setstr(ValueError, "path too long");
  352.         return NULL;
  353.     }
  354.     strcpy(namebuf, name);
  355.     if (namebuf[len-1] != '/' && namebuf[len-1] != '\\')
  356.         namebuf[len++] = '/';
  357.     strcpy(namebuf + len, "*.*");
  358.  
  359.     if ((d = newlistobject(0)) == NULL)
  360.         return NULL;
  361.  
  362.     hFindFile = FindFirstFile(namebuf, &FileData);
  363.     if (hFindFile == INVALID_HANDLE_VALUE) {
  364.         errno = GetLastError();
  365.         return posix_error();
  366.     }
  367.     do {
  368.         v = newstringobject(FileData.cFileName);
  369.         if (v == NULL) {
  370.             DECREF(d);
  371.             d = NULL;
  372.             break;
  373.         }
  374.         if (addlistitem(d, v) != 0) {
  375.             DECREF(v);
  376.             DECREF(d);
  377.             d = NULL;
  378.             break;
  379.         }
  380.         DECREF(v);
  381.     } while (FindNextFile(hFindFile, &FileData) == TRUE);
  382.  
  383.     if (FindClose(hFindFile) == FALSE) {
  384.         errno = GetLastError();
  385.         return posix_error();
  386.     }
  387.  
  388.     return d;
  389.  
  390. #else /* !NT */
  391.  
  392.     char *name;
  393.     object *d, *v;
  394.     DIR *dirp;
  395.     struct dirent *ep;
  396.     if (!getargs(args, "s", &name))
  397.         return NULL;
  398.     BGN_SAVE
  399.     if ((dirp = opendir(name)) == NULL) {
  400.         RET_SAVE
  401.         return posix_error();
  402.     }
  403.     if ((d = newlistobject(0)) == NULL) {
  404.         closedir(dirp);
  405.         RET_SAVE
  406.         return NULL;
  407.     }
  408.     while ((ep = readdir(dirp)) != NULL) {
  409.         v = newstringobject(ep->d_name);
  410.         if (v == NULL) {
  411.             DECREF(d);
  412.             d = NULL;
  413.             break;
  414.         }
  415.         if (addlistitem(d, v) != 0) {
  416.             DECREF(v);
  417.             DECREF(d);
  418.             d = NULL;
  419.             break;
  420.         }
  421.         DECREF(v);
  422.     }
  423.     closedir(dirp);
  424.     END_SAVE
  425.  
  426.     return d;
  427.  
  428. #endif /* !NT */
  429. }
  430.  
  431. static object *
  432. posix_mkdir(self, args)
  433.     object *self;
  434.     object *args;
  435. {
  436.     return posix_strint(args, mkdir);
  437. }
  438.  
  439. #ifdef HAVE_NICE
  440. static object *
  441. posix_nice(self, args)
  442.     object *self;
  443.     object *args;
  444. {
  445.     int increment, value;
  446.  
  447.     if (!getargs(args, "i", &increment))
  448.         return NULL;
  449.     value = nice(increment);
  450.     if (value == -1)
  451.         return posix_error();
  452.     return newintobject((long) value);
  453. }
  454. #endif /* HAVE_NICE */
  455.  
  456. static object *
  457. posix_rename(self, args)
  458.     object *self;
  459.     object *args;
  460. {
  461.     return posix_2str(args, rename);
  462. }
  463.  
  464. static object *
  465. posix_rmdir(self, args)
  466.     object *self;
  467.     object *args;
  468. {
  469.     return posix_1str(args, rmdir);
  470. }
  471.  
  472. static object *
  473. posix_stat(self, args)
  474.     object *self;
  475.     object *args;
  476. {
  477.     return posix_do_stat(self, args, stat);
  478. }
  479.  
  480. static object *
  481. posix_system(self, args)
  482.     object *self;
  483.     object *args;
  484. {
  485.     char *command;
  486.     long sts;
  487.     if (!getargs(args, "s", &command))
  488.         return NULL;
  489.     BGN_SAVE
  490.     sts = system(command);
  491.     END_SAVE
  492.     return newintobject(sts);
  493. }
  494.  
  495. static object *
  496. posix_umask(self, args)
  497.     object *self;
  498.     object *args;
  499. {
  500.     int i;
  501.     if (!getintarg(args, &i))
  502.         return NULL;
  503.     i = umask(i);
  504.     if (i < 0)
  505.         return posix_error();
  506.     return newintobject((long)i);
  507. }
  508.  
  509. static object *
  510. posix_unlink(self, args)
  511.     object *self;
  512.     object *args;
  513. {
  514.     return posix_1str(args, unlink);
  515. }
  516.  
  517. #ifdef HAVE_UNAME
  518. static object *
  519. posix_uname(self, args)
  520.     object *self;
  521.     object *args;
  522. {
  523.     struct utsname u;
  524.     object *v;
  525.     int res;
  526.     if (!getnoarg(args))
  527.         return NULL;
  528.     BGN_SAVE
  529.     res = uname(&u);
  530.     END_SAVE
  531.     if (res < 0)
  532.         return posix_error();
  533.     return mkvalue("(sssss)",
  534.                u.sysname,
  535.                u.nodename,
  536.                u.release,
  537.                u.version,
  538.                u.machine);
  539. }
  540. #endif /* HAVE_UNAME */
  541.  
  542. static object *
  543. posix_utime(self, args)
  544.     object *self;
  545.     object *args;
  546. {
  547.     char *path;
  548.     int res;
  549.  
  550. #ifdef HAVE_UTIME_H
  551.     struct utimbuf buf;
  552. #define ATIME buf.actime
  553. #define MTIME buf.modtime
  554. #define UTIME_ARG &buf
  555. #else /* HAVE_UTIME_H */
  556.     time_t buf[2];
  557. #define ATIME buf[0]
  558. #define MTIME buf[1]
  559. #define UTIME_ARG buf
  560. #endif /* HAVE_UTIME_H */
  561.  
  562.     if (!getargs(args, "(s(ll))", &path, &ATIME, &MTIME))
  563.         return NULL;
  564.     BGN_SAVE
  565.     res = utime(path, UTIME_ARG);
  566.     END_SAVE
  567.     if (res < 0)
  568.         return posix_error();
  569.     INCREF(None);
  570.     return None;
  571. #undef UTIME_ARG
  572. #undef ATIME
  573. #undef MTIME
  574. }
  575.  
  576.  
  577. /* Process operations */
  578.  
  579. static object *
  580. posix__exit(self, args)
  581.     object *self;
  582.     object *args;
  583. {
  584.     int sts;
  585.     if (!getintarg(args, &sts))
  586.         return NULL;
  587.     _exit(sts);
  588.     /* NOTREACHED */
  589. }
  590.  
  591. static object *
  592. posix_execv(self, args)
  593.     object *self;
  594.     object *args;
  595. {
  596.     char *path;
  597.     object *argv;
  598.     char **argvlist;
  599.     int i, argc;
  600.     object *(*getitem) PROTO((object *, int));
  601.  
  602.     /* execv has two arguments: (path, argv), where
  603.        argv is a list or tuple of strings. */
  604.  
  605.     if (!getargs(args, "(sO)", &path, &argv))
  606.         return NULL;
  607.     if (is_listobject(argv)) {
  608.         argc = getlistsize(argv);
  609.         getitem = getlistitem;
  610.     }
  611.     else if (is_tupleobject(argv)) {
  612.         argc = gettuplesize(argv);
  613.         getitem = gettupleitem;
  614.     }
  615.     else {
  616.  badarg:
  617.         err_badarg();
  618.         return NULL;
  619.     }
  620.  
  621.     argvlist = NEW(char *, argc+1);
  622.     if (argvlist == NULL)
  623.         return NULL;
  624.     for (i = 0; i < argc; i++) {
  625.         if (!getargs((*getitem)(argv, i), "s", &argvlist[i])) {
  626.             DEL(argvlist);
  627.             goto badarg;
  628.         }
  629.     }
  630.     argvlist[argc] = NULL;
  631.  
  632. #ifdef BAD_EXEC_PROTOTYPES
  633.     execv(path, (const char **) argvlist);
  634. #else /* BAD_EXEC_PROTOTYPES */
  635.     execv(path, argvlist);
  636. #endif /* BAD_EXEC_PROTOTYPES */
  637.  
  638.     /* If we get here it's definitely an error */
  639.  
  640.     DEL(argvlist);
  641.     return posix_error();
  642. }
  643.  
  644. static object *
  645. posix_execve(self, args)
  646.     object *self;
  647.     object *args;
  648. {
  649.     char *path;
  650.     object *argv, *env;
  651.     char **argvlist;
  652.     char **envlist;
  653.     object *key, *val;
  654.     int i, pos, argc, envc;
  655.     object *(*getitem) PROTO((object *, int));
  656.  
  657.     /* execve has three arguments: (path, argv, env), where
  658.        argv is a list or tuple of strings and env is a dictionary
  659.        like posix.environ. */
  660.  
  661.     if (!getargs(args, "(sOO)", &path, &argv, &env))
  662.         return NULL;
  663.     if (is_listobject(argv)) {
  664.         argc = getlistsize(argv);
  665.         getitem = getlistitem;
  666.     }
  667.     else if (is_tupleobject(argv)) {
  668.         argc = gettuplesize(argv);
  669.         getitem = gettupleitem;
  670.     }
  671.     else {
  672.         err_setstr(TypeError, "argv must be tuple or list");
  673.         return NULL;
  674.     }
  675.     if (!is_dictobject(env)) {
  676.         err_setstr(TypeError, "env must be dictionary");
  677.         return NULL;
  678.     }
  679.  
  680.     argvlist = NEW(char *, argc+1);
  681.     if (argvlist == NULL) {
  682.         err_nomem();
  683.         return NULL;
  684.     }
  685.     for (i = 0; i < argc; i++) {
  686.         if (!getargs((*getitem)(argv, i),
  687.                  "s;argv must be list of strings",
  688.                  &argvlist[i])) {
  689.             goto fail_1;
  690.         }
  691.     }
  692.     argvlist[argc] = NULL;
  693.  
  694.     i = getmappingsize(env);
  695.     envlist = NEW(char *, i + 1);
  696.     if (envlist == NULL) {
  697.         err_nomem();
  698.         goto fail_1;
  699.     }
  700.     pos = 0;
  701.     envc = 0;
  702.     while (mappinggetnext(env, &pos, &key, &val)) {
  703.         char *p, *k, *v;
  704.         if (!getargs(key, "s;non-string key in env", &k) ||
  705.             !getargs(val, "s;non-string value in env", &v)) {
  706.             goto fail_2;
  707.         }
  708.         p = NEW(char, getstringsize(key) + getstringsize(val) + 2);
  709.         if (p == NULL) {
  710.             err_nomem();
  711.             goto fail_2;
  712.         }
  713.         sprintf(p, "%s=%s", k, v);
  714.         envlist[envc++] = p;
  715.     }
  716.     envlist[envc] = 0;
  717.  
  718.  
  719. #ifdef BAD_EXEC_PROTOTYPES
  720.     execve(path, (const char **)argvlist, envlist);
  721. #else /* BAD_EXEC_PROTOTYPES */
  722.     execve(path, argvlist, envlist);
  723. #endif /* BAD_EXEC_PROTOTYPES */
  724.     
  725.     /* If we get here it's definitely an error */
  726.  
  727.     (void) posix_error();
  728.  
  729.  fail_2:
  730.     while (--envc >= 0)
  731.         DEL(envlist[envc]);
  732.     DEL(envlist);
  733.  fail_1:
  734.     DEL(argvlist);
  735.  
  736.     return NULL;
  737. }
  738.  
  739. #ifndef NT
  740. static object *
  741. posix_fork(self, args)
  742.     object *self;
  743.     object *args;
  744. {
  745.     int pid;
  746.     if (!getnoarg(args))
  747.         return NULL;
  748.     pid = fork();
  749.     if (pid == -1)
  750.         return posix_error();
  751.     return newintobject((long)pid);
  752. }
  753.  
  754. static object *
  755. posix_getegid(self, args)
  756.     object *self;
  757.     object *args;
  758. {
  759.     if (!getnoarg(args))
  760.         return NULL;
  761.     return newintobject((long)getegid());
  762. }
  763.  
  764. static object *
  765. posix_geteuid(self, args)
  766.     object *self;
  767.     object *args;
  768. {
  769.     if (!getnoarg(args))
  770.         return NULL;
  771.     return newintobject((long)geteuid());
  772. }
  773.  
  774. static object *
  775. posix_getgid(self, args)
  776.     object *self;
  777.     object *args;
  778. {
  779.     if (!getnoarg(args))
  780.         return NULL;
  781.     return newintobject((long)getgid());
  782. }
  783. #endif /* !NT */
  784.  
  785. static object *
  786. posix_getpid(self, args)
  787.     object *self;
  788.     object *args;
  789. {
  790.     if (!getnoarg(args))
  791.         return NULL;
  792.     return newintobject((long)getpid());
  793. }
  794.  
  795. #ifdef HAVE_GETPGRP
  796. static object *
  797. posix_getpgrp(self, args)
  798.     object *self;
  799.     object *args;
  800. {
  801.     if (!getnoarg(args))
  802.         return NULL;
  803. #ifdef GETPGRP_HAVE_ARG
  804.     return newintobject((long)getpgrp(0));
  805. #else /* GETPGRP_HAVE_ARG */
  806.     return newintobject((long)getpgrp());
  807. #endif /* GETPGRP_HAVE_ARG */
  808. }
  809. #endif /* HAVE_GETPGRP */
  810.  
  811. #ifdef HAVE_SETPGRP
  812. static object *
  813. posix_setpgrp(self, args)
  814.     object *self;
  815.     object *args;
  816. {
  817.     if (!getnoarg(args))
  818.         return NULL;
  819. #ifdef GETPGRP_HAVE_ARG
  820.     if (setpgrp(0, 0) < 0)
  821. #else /* GETPGRP_HAVE_ARG */
  822.     if (setpgrp() < 0)
  823. #endif /* GETPGRP_HAVE_ARG */
  824.         return posix_error();
  825.     INCREF(None);
  826.     return None;
  827. }
  828.  
  829. #endif /* HAVE_SETPGRP */
  830.  
  831. #ifndef NT
  832. static object *
  833. posix_getppid(self, args)
  834.     object *self;
  835.     object *args;
  836. {
  837.     if (!getnoarg(args))
  838.         return NULL;
  839.     return newintobject((long)getppid());
  840. }
  841.  
  842. static object *
  843. posix_getuid(self, args)
  844.     object *self;
  845.     object *args;
  846. {
  847.     if (!getnoarg(args))
  848.         return NULL;
  849.     return newintobject((long)getuid());
  850. }
  851.  
  852. static object *
  853. posix_kill(self, args)
  854.     object *self;
  855.     object *args;
  856. {
  857.     int pid, sig;
  858.     if (!getargs(args, "(ii)", &pid, &sig))
  859.         return NULL;
  860.     if (kill(pid, sig) == -1)
  861.         return posix_error();
  862.     INCREF(None);
  863.     return None;
  864. }
  865. #endif /* !NT */
  866.  
  867. static object *
  868. posix_popen(self, args)
  869.     object *self;
  870.     object *args;
  871. {
  872.     char *name, *mode;
  873.     FILE *fp;
  874.     if (!getargs(args, "(ss)", &name, &mode))
  875.         return NULL;
  876.     BGN_SAVE
  877.     fp = popen(name, mode);
  878.     END_SAVE
  879.     if (fp == NULL)
  880.         return posix_error();
  881.     return newopenfileobject(fp, name, mode, pclose);
  882. }
  883.  
  884. #ifdef HAVE_SETUID
  885. static object *
  886. posix_setuid(self, args)
  887.     object *self;
  888.     object *args;
  889. {
  890.     int uid;
  891.     if (!getargs(args, "i", &uid))
  892.         return NULL;
  893.     if (setuid(uid) < 0)
  894.         return posix_error();
  895.     INCREF(None);
  896.     return None;
  897. }
  898. #endif /* HAVE_SETUID */
  899.  
  900. #ifdef HAVE_SETGID
  901. static object *
  902. posix_setgid(self, args)
  903.     object *self;
  904.     object *args;
  905. {
  906.     int gid;
  907.     if (!getargs(args, "i", &gid))
  908.         return NULL;
  909.     if (setgid(gid) < 0)
  910.         return posix_error();
  911.     INCREF(None);
  912.     return None;
  913. }
  914. #endif /* HAVE_SETGID */
  915.  
  916. #ifdef HAVE_WAITPID
  917. static object *
  918. posix_waitpid(self, args)
  919.     object *self;
  920.     object *args;
  921. {
  922.     int pid, options, sts;
  923.     if (!getargs(args, "(ii)", &pid, &options))
  924.         return NULL;
  925.     BGN_SAVE
  926.     pid = waitpid(pid, &sts, options);
  927.     END_SAVE
  928.     if (pid == -1)
  929.         return posix_error();
  930.     else
  931.         return mkvalue("ii", pid, sts);
  932. }
  933. #endif /* HAVE_WAITPID */
  934.  
  935. #ifndef NT
  936. static object *
  937. posix_wait(self, args)
  938.     object *self;
  939.     object *args;
  940. {
  941.     int pid, sts;
  942.     BGN_SAVE
  943.     pid = wait(&sts);
  944.     END_SAVE
  945.     if (pid == -1)
  946.         return posix_error();
  947.     else
  948.         return mkvalue("ii", pid, sts);
  949. }
  950. #endif /* !NT */
  951.  
  952. static object *
  953. posix_lstat(self, args)
  954.     object *self;
  955.     object *args;
  956. {
  957. #ifdef HAVE_LSTAT
  958.     return posix_do_stat(self, args, lstat);
  959. #else /* !HAVE_LSTAT */
  960.     return posix_do_stat(self, args, stat);
  961. #endif /* !HAVE_LSTAT */
  962. }
  963.  
  964. #ifdef HAVE_READLINK
  965. static object *
  966. posix_readlink(self, args)
  967.     object *self;
  968.     object *args;
  969. {
  970.     char buf[MAXPATHLEN];
  971.     char *path;
  972.     int n;
  973.     if (!getargs(args, "s", &path))
  974.         return NULL;
  975.     BGN_SAVE
  976.     n = readlink(path, buf, (int) sizeof buf);
  977.     END_SAVE
  978.     if (n < 0)
  979.         return posix_error();
  980.     return newsizedstringobject(buf, n);
  981. }
  982. #endif /* HAVE_READLINK */
  983.  
  984. #ifdef HAVE_SYMLINK
  985. static object *
  986. posix_symlink(self, args)
  987.     object *self;
  988.     object *args;
  989. {
  990.     return posix_2str(args, symlink);
  991. }
  992. #endif /* HAVE_SYMLINK */
  993.  
  994. #ifdef HAVE_TIMES
  995. #ifndef HZ
  996. #define HZ 60 /* Universal constant :-) */
  997. #endif /* HZ */
  998. static object *
  999. posix_times(self, args)
  1000.     object *self;
  1001.     object *args;
  1002. {
  1003.     struct tms t;
  1004.     clock_t c;
  1005.     if (!getnoarg(args))
  1006.         return NULL;
  1007.     errno = 0;
  1008.     c = times(&t);
  1009.     if (c == (clock_t) -1)
  1010.         return posix_error();
  1011.     return mkvalue("dddd",
  1012.                (double)t.tms_utime / HZ,
  1013.                (double)t.tms_stime / HZ,
  1014.                (double)t.tms_cutime / HZ,
  1015.                (double)t.tms_cstime / HZ);
  1016. }
  1017. #endif /* HAVE_TIMES */
  1018. #ifdef NT
  1019. #define HAVE_TIMES    /* so the method table will pick it up */
  1020. static object *
  1021. posix_times(self, args)
  1022.     object *self;
  1023.     object *args;
  1024. {
  1025.     FILETIME create, exit, kernel, user;
  1026.     HANDLE hProc;
  1027.     if (!getnoarg(args))
  1028.         return NULL;
  1029.     hProc = GetCurrentProcess();
  1030.     GetProcessTimes(hProc,&create, &exit, &kernel, &user);
  1031.     return mkvalue("dddd",
  1032.                (double)(kernel.dwHighDateTime*2E32+kernel.dwLowDateTime) / 2E6,
  1033.                (double)(user.dwHighDateTime*2E32+user.dwLowDateTime) / 2E6,
  1034.                (double)0,
  1035.                (double)0);
  1036. }
  1037. #endif /* NT */
  1038.  
  1039. #ifdef HAVE_SETSID
  1040. static object *
  1041. posix_setsid(self, args)
  1042.     object *self;
  1043.     object *args;
  1044. {
  1045.     if (!getnoarg(args))
  1046.         return NULL;
  1047.     if (setsid() < 0)
  1048.         return posix_error();
  1049.     INCREF(None);
  1050.     return None;
  1051. }
  1052. #endif /* HAVE_SETSID */
  1053.  
  1054. #ifdef HAVE_SETPGID
  1055. static object *
  1056. posix_setpgid(self, args)
  1057.     object *self;
  1058.     object *args;
  1059. {
  1060.     int pid, pgrp;
  1061.     if (!getargs(args, "(ii)", &pid, &pgrp))
  1062.         return NULL;
  1063.     if (setpgid(pid, pgrp) < 0)
  1064.         return posix_error();
  1065.     INCREF(None);
  1066.     return None;
  1067. }
  1068. #endif /* HAVE_SETPGID */
  1069.  
  1070. #ifdef HAVE_TCGETPGRP
  1071. static object *
  1072. posix_tcgetpgrp(self, args)
  1073.     object *self;
  1074.     object *args;
  1075. {
  1076.     int fd, pgid;
  1077.     if (!getargs(args, "i", &fd))
  1078.         return NULL;
  1079.     pgid = tcgetpgrp(fd);
  1080.     if (pgid < 0)
  1081.         return posix_error();
  1082.     return newintobject((long)pgid);
  1083. }
  1084. #endif /* HAVE_TCGETPGRP */
  1085.  
  1086. #ifdef HAVE_TCSETPGRP
  1087. static object *
  1088. posix_tcsetpgrp(self, args)
  1089.     object *self;
  1090.     object *args;
  1091. {
  1092.     int fd, pgid;
  1093.     if (!getargs(args, "(ii)", &fd, &pgid))
  1094.         return NULL;
  1095.     if (tcsetpgrp(fd, pgid) < 0)
  1096.         return posix_error();
  1097.        INCREF(None);
  1098.     return None;
  1099. }
  1100. #endif /* HAVE_TCSETPGRP */
  1101.  
  1102. /* Functions acting on file descriptors */
  1103.  
  1104. static object *
  1105. posix_open(self, args)
  1106.     object *self;
  1107.     object *args;
  1108. {
  1109.     char *file;
  1110.     int flag;
  1111.     int mode = 0777;
  1112.     int fd;
  1113.     if (!getargs(args, "(si)", &file, &flag)) {
  1114.         err_clear();
  1115.         if (!getargs(args, "(sii)", &file, &flag, &mode))
  1116.             return NULL;
  1117.     }
  1118.     BGN_SAVE
  1119.     fd = open(file, flag, mode);
  1120.     END_SAVE
  1121.     if (fd < 0)
  1122.         return posix_error();
  1123.     return newintobject((long)fd);
  1124. }
  1125.  
  1126. static object *
  1127. posix_close(self, args)
  1128.     object *self;
  1129.     object *args;
  1130. {
  1131.     int fd, res;
  1132.     if (!getargs(args, "i", &fd))
  1133.         return NULL;
  1134.     BGN_SAVE
  1135.     res = close(fd);
  1136.     END_SAVE
  1137.     if (res < 0)
  1138.         return posix_error();
  1139.     INCREF(None);
  1140.     return None;
  1141. }
  1142.  
  1143. static object *
  1144. posix_dup(self, args)
  1145.     object *self;
  1146.     object *args;
  1147. {
  1148.     int fd;
  1149.     if (!getargs(args, "i", &fd))
  1150.         return NULL;
  1151.     BGN_SAVE
  1152.     fd = dup(fd);
  1153.     END_SAVE
  1154.     if (fd < 0)
  1155.         return posix_error();
  1156.     return newintobject((long)fd);
  1157. }
  1158.  
  1159. static object *
  1160. posix_dup2(self, args)
  1161.     object *self;
  1162.     object *args;
  1163. {
  1164.     int fd, fd2, res;
  1165.     if (!getargs(args, "(ii)", &fd, &fd2))
  1166.         return NULL;
  1167.     BGN_SAVE
  1168.     res = dup2(fd, fd2);
  1169.     END_SAVE
  1170.     if (res < 0)
  1171.         return posix_error();
  1172.     INCREF(None);
  1173.     return None;
  1174. }
  1175.  
  1176. static object *
  1177. posix_lseek(self, args)
  1178.     object *self;
  1179.     object *args;
  1180. {
  1181.     int fd, how;
  1182.     long pos, res;
  1183.     if (!getargs(args, "(ili)", &fd, &pos, &how))
  1184.         return NULL;
  1185. #ifdef SEEK_SET
  1186.     /* Turn 0, 1, 2 into SEEK_{SET,CUR,END} */
  1187.     switch (how) {
  1188.     case 0: how = SEEK_SET; break;
  1189.     case 1: how = SEEK_CUR; break;
  1190.     case 2: how = SEEK_END; break;
  1191.     }
  1192. #endif /* SEEK_END */
  1193.     BGN_SAVE
  1194.     res = lseek(fd, pos, how);
  1195.     END_SAVE
  1196.     if (res < 0)
  1197.         return posix_error();
  1198.     return newintobject(res);
  1199. }
  1200.  
  1201. static object *
  1202. posix_read(self, args)
  1203.     object *self;
  1204.     object *args;
  1205. {
  1206.     int fd, size;
  1207.     object *buffer;
  1208.     if (!getargs(args, "(ii)", &fd, &size))
  1209.         return NULL;
  1210.     buffer = newsizedstringobject((char *)NULL, size);
  1211.     if (buffer == NULL)
  1212.         return NULL;
  1213.     BGN_SAVE
  1214.     size = read(fd, getstringvalue(buffer), size);
  1215.     END_SAVE
  1216.     if (size < 0) {
  1217.         DECREF(buffer);
  1218.         return posix_error();
  1219.     }
  1220.     resizestring(&buffer, size);
  1221.     return buffer;
  1222. }
  1223.  
  1224. static object *
  1225. posix_write(self, args)
  1226.     object *self;
  1227.     object *args;
  1228. {
  1229.     int fd, size;
  1230.     char *buffer;
  1231.     if (!getargs(args, "(is#)", &fd, &buffer, &size))
  1232.         return NULL;
  1233.     BGN_SAVE
  1234.     size = write(fd, buffer, size);
  1235.     END_SAVE
  1236.     if (size < 0)
  1237.         return posix_error();
  1238.     return newintobject((long)size);
  1239. }
  1240.  
  1241. static object *
  1242. posix_fstat(self, args)
  1243.     object *self;
  1244.     object *args;
  1245. {
  1246.     int fd;
  1247.     struct stat st;
  1248.     int res;
  1249.     if (!getargs(args, "i", &fd))
  1250.         return NULL;
  1251.     BGN_SAVE
  1252.     res = fstat(fd, &st);
  1253.     END_SAVE
  1254.     if (res != 0)
  1255.         return posix_error();
  1256.     return mkvalue("(llllllllll)",
  1257.             (long)st.st_mode,
  1258.             (long)st.st_ino,
  1259.             (long)st.st_dev,
  1260.             (long)st.st_nlink,
  1261.             (long)st.st_uid,
  1262.             (long)st.st_gid,
  1263.             (long)st.st_size,
  1264.             (long)st.st_atime,
  1265.             (long)st.st_mtime,
  1266.             (long)st.st_ctime);
  1267. }
  1268.  
  1269. static object *
  1270. posix_fdopen(self, args)
  1271.     object *self;
  1272.     object *args;
  1273. {
  1274.     extern int fclose PROTO((FILE *));
  1275.     int fd;
  1276.     char *mode;
  1277.     FILE *fp;
  1278.     if (!getargs(args, "(is)", &fd, &mode))
  1279.         return NULL;
  1280.     BGN_SAVE
  1281.     fp = fdopen(fd, mode);
  1282.     END_SAVE
  1283.     if (fp == NULL)
  1284.         return posix_error();
  1285.     /* From now on, ignore SIGPIPE and let the error checking
  1286.        do the work. */
  1287.     return newopenfileobject(fp, "(fdopen)", mode, fclose);
  1288. }
  1289.  
  1290. static object *
  1291. posix_pipe(self, args)
  1292.     object *self;
  1293.     object *args;
  1294. {
  1295. #ifndef NT
  1296.     int fds[2];
  1297.     int res;
  1298.     if (!getargs(args, ""))
  1299.         return NULL;
  1300.     BGN_SAVE
  1301.     res = pipe(fds);
  1302.     END_SAVE
  1303.     if (res != 0)
  1304.         return posix_error();
  1305.     return mkvalue("(ii)", fds[0], fds[1]);
  1306. #else /* NT */
  1307.     HANDLE read, write;
  1308.     BOOL ok;
  1309.     if (!getargs(args, ""))
  1310.         return NULL;
  1311.     BGN_SAVE
  1312.     ok = CreatePipe( &read, &write, NULL, 0);
  1313.     END_SAVE
  1314.     if (!ok)
  1315.         return posix_error();
  1316.     return mkvalue("(ii)", read, write);
  1317. #endif /* NT */
  1318. }
  1319.  
  1320. static struct methodlist posix_methods[] = {
  1321.     {"chdir",    posix_chdir},
  1322.     {"chmod",    posix_chmod},
  1323. #ifdef HAVE_CHOWN
  1324.     {"chown",    posix_chown},
  1325. #endif /* HAVE_CHOWN */
  1326.     {"getcwd",    posix_getcwd},
  1327. #ifdef HAVE_LINK
  1328.     {"link",    posix_link},
  1329. #endif /* HAVE_LINK */
  1330.     {"listdir",    posix_listdir},
  1331.     {"lstat",    posix_lstat},
  1332.     {"mkdir",    posix_mkdir},
  1333. #ifdef HAVE_NICE
  1334.     {"nice",    posix_nice},
  1335. #endif /* HAVE_NICE */
  1336. #ifdef HAVE_READLINK
  1337.     {"readlink",    posix_readlink},
  1338. #endif /* HAVE_READLINK */
  1339.     {"rename",    posix_rename},
  1340.     {"rmdir",    posix_rmdir},
  1341.     {"stat",    posix_stat},
  1342. #ifdef HAVE_SYMLINK
  1343.     {"symlink",    posix_symlink},
  1344. #endif /* HAVE_SYMLINK */
  1345.     {"system",    posix_system},
  1346.     {"umask",    posix_umask},
  1347. #ifdef HAVE_UNAME
  1348.     {"uname",    posix_uname},
  1349. #endif /* HAVE_UNAME */
  1350.     {"unlink",    posix_unlink},
  1351.     {"utime",    posix_utime},
  1352. #ifdef HAVE_TIMES
  1353.     {"times",    posix_times},
  1354. #endif /* HAVE_TIMES */
  1355.     {"_exit",    posix__exit},
  1356.     {"execv",    posix_execv},
  1357.     {"execve",    posix_execve},
  1358. #ifndef NT
  1359.     {"fork",    posix_fork},
  1360.     {"getegid",    posix_getegid},
  1361.     {"geteuid",    posix_geteuid},
  1362.     {"getgid",    posix_getgid},
  1363. #endif /* !NT */
  1364.     {"getpid",    posix_getpid},
  1365. #ifdef HAVE_GETPGRP
  1366.     {"getpgrp",    posix_getpgrp},
  1367. #endif /* HAVE_GETPGRP */
  1368. #ifndef NT
  1369.     {"getppid",    posix_getppid},
  1370.     {"getuid",    posix_getuid},
  1371.     {"kill",    posix_kill},
  1372. #endif /* !NT */
  1373.     {"popen",    posix_popen},
  1374. #ifdef HAVE_SETUID
  1375.     {"setuid",    posix_setuid},
  1376. #endif /* HAVE_SETUID */
  1377. #ifdef HAVE_SETGID
  1378.     {"setgid",    posix_setgid},
  1379. #endif /* HAVE_SETGID */
  1380. #ifdef HAVE_SETPGRP
  1381.     {"setpgrp",    posix_setpgrp},
  1382. #endif /* HAVE_SETPGRP */
  1383. #ifndef NT
  1384.     {"wait",    posix_wait},
  1385. #endif /* !NT */
  1386. #ifdef HAVE_WAITPID
  1387.     {"waitpid",    posix_waitpid},
  1388. #endif /* HAVE_WAITPID */
  1389. #ifdef HAVE_SETSID
  1390.     {"setsid",    posix_setsid},
  1391. #endif /* HAVE_SETSID */
  1392. #ifdef HAVE_SETPGID
  1393.     {"setpgid",    posix_setpgid},
  1394. #endif /* HAVE_SETPGID */
  1395. #ifdef HAVE_TCGETPGRP
  1396.     {"tcgetpgrp",    posix_tcgetpgrp},
  1397. #endif /* HAVE_TCGETPGRP */
  1398. #ifdef HAVE_TCSETPGRP
  1399.     {"tcsetpgrp",    posix_tcsetpgrp},
  1400. #endif /* HAVE_TCSETPGRP */
  1401.     {"open",    posix_open},
  1402.     {"close",    posix_close},
  1403.     {"dup",        posix_dup},
  1404.     {"dup2",    posix_dup2},
  1405.     {"lseek",    posix_lseek},
  1406.     {"read",    posix_read},
  1407.     {"write",    posix_write},
  1408.     {"fstat",    posix_fstat},
  1409.     {"fdopen",    posix_fdopen},
  1410.     {"pipe",    posix_pipe},
  1411.     {NULL,        NULL}         /* Sentinel */
  1412. };
  1413.  
  1414.  
  1415. #ifdef NT
  1416. void
  1417. initnt()
  1418. {
  1419.     object *m, *d, *v;
  1420.     
  1421.     m = initmodule("nt", posix_methods);
  1422.     d = getmoduledict(m);
  1423.     
  1424.     /* Initialize nt.environ dictionary */
  1425.     v = convertenviron();
  1426.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1427.         fatal("can't define nt.environ");
  1428.     DECREF(v);
  1429.     
  1430.     /* Initialize nt.error exception */
  1431.     PosixError = newstringobject("nt.error");
  1432.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1433.         fatal("can't define nt.error");
  1434. }
  1435. #else /* !NT */
  1436. void
  1437. initposix()
  1438. {
  1439.     object *m, *d, *v;
  1440.     
  1441.     m = initmodule("posix", posix_methods);
  1442.     d = getmoduledict(m);
  1443.     
  1444.     /* Initialize posix.environ dictionary */
  1445.     v = convertenviron();
  1446.     if (v == NULL || dictinsert(d, "environ", v) != 0)
  1447.         fatal("can't define posix.environ");
  1448.     DECREF(v);
  1449.     
  1450.     /* Initialize posix.error exception */
  1451.     PosixError = newstringobject("posix.error");
  1452.     if (PosixError == NULL || dictinsert(d, "error", PosixError) != 0)
  1453.         fatal("can't define posix.error");
  1454. }
  1455. #endif /* !NT */
  1456.